package org.office.api.utils;


import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

/** 
 * xml读取工具类
 *
 * <pre> 
 * 构建组：office-api
 * 作者：eddy
 * 邮箱：1546077710@qq.com
 * 日期：2016年11月2日-下午1:37:02
 * 版权：
 * </pre>
 */
public class Dom4jUtil {

	/**
	 * 得到子元素节点的文本
	 * @param element 
	 * @param element_name child node 名称
	 * @param isReturnNull 是否允许节点文本内容为空 true:是 false:否
	 * @return
	 */
	public static String getChildString(Element element,String element_name,boolean isReturnNull) throws Exception{
		try {
			return getChildString(element, element_name, isReturnNull, true);
		} catch (Exception e) {
			throw e;
		}
	}
	
	/**
	 * 得到子元素节点的文本 附带清除制表回车符
	 * @param element 
	 * @param element_name child node 名称
	 * @param isReturnNull 是否允许节点文本内容为空 true:是 false:否
	 * @param clearNewLineChar 文本是否清除回车和制表符  true:是 false:否
	 * @return
	 */
	public static String getChildString(Element element,String element_name,
			boolean isReturnNull, boolean clearNewLineChar) throws Exception{
		Element child = element.element(element_name);
		if(child == null) {
			if (isReturnNull)
				return "";
			else
				throw new Exception("不能得到节点下｛" + element.getQualifiedName()
					+ "｝的元素：" + element_name);
		}
		if (clearNewLineChar)
			return swithChar(child.getTextTrim());
		else
			return child.getTextTrim();
	}
	
	/**
	 * 得到子元素节点的Boolean内容
	 * @param element
	 * @param element_name
	 * @param isReturnNull
	 * @return
	 */
	public static Boolean getChildBoolean(Element element,String element_name,
			boolean isReturnNull) throws Exception{
		Element child = element.element(element_name);
		if(child == null) {
			if (isReturnNull)
				return null;
			else
				throw new Exception("不能得到节点下｛" + element.getQualifiedName()
					+ "｝的元素：" + element_name);
		}
		if (child.getTextTrim().toLowerCase().equals("true"))
			return Boolean.TRUE;
		else
			return Boolean.FALSE;
	}
	
	/**
	 * 得到子元素节点的整数内容
	 * @param element
	 * @param element_name
	 * @param isReturnNull 是否内容为空 true:是 false:否
	 * @return
	 */
	public static Integer getChildInteger(Element element,String element_name,
			boolean isReturnNull) throws Exception{
		Element child = element.element(element_name);
		if(child == null) {
			if (isReturnNull)
				return null;
			else
				throw new Exception("不能得到节点下｛" + element.getQualifiedName()
					+ "｝的元素：" + element_name);
		}
		if (child.getTextTrim().equals(""))
			return null;
		else
			return new Integer(child.getTextTrim());
		
	}
	
	/**
	 * 得到节点的AttributeValue 文本
	 * @param element
	 * @param attrib_name 属性名称
	 * @param isReturnNull 是否内容为空 true:是 false:否
	 * @return
	 */
	public static String getAttributeString(Element element,String attrib_name, 
			boolean isReturnNull) throws Exception{
		
		if(element == null && isReturnNull) {
			if(isReturnNull) {
				return "";	
			}
			else {
				throw new Exception(attrib_name + "元素不存在");
			}	
		}
		String value = element.attributeValue(attrib_name);
		
		if(value != null && !value.equals("")) {
			if(value.indexOf("#") == 0) {
				value = value.substring(1,value.length());
			}
		}
		
		if (value == null) {
			if (isReturnNull)
				return "";
			else
				throw new Exception("不能得到节点下｛" + element.getQualifiedName()
					+ "｝的元素：" + attrib_name);
		}
		return value;
	}
	
	/**
	 * 得到子节点的 Attribute 属性
	 * @param element 
	 * @param child_element_name 子节点名称
	 * @param attrib_name 属性名称
	 * @param isReturnNull 是否内容为空 true:是 false:否
	 * @return
	 */
	public static String getChildAttributeString(Element element,String child_element_name,String attrib_name, 
		boolean isReturnNull) throws Exception{
		List<Element> childList = element.elements(child_element_name);

		if(childList != null && childList.size() != 0) {
			String result = "";
			for(int i = 0; i < childList.size(); i++)
			{
				String attr = getAttributeString((Element)childList.get(i),attrib_name,isReturnNull);
				result = result + attr + ",";
			}
			result = result.substring(0, result.length()-1);
			return result;
		}
		else {
			if(isReturnNull) {
				return "";
			}
			else {
				throw new Exception("不能得到节点下｛" + child_element_name
						+ "｝的元素：" + attrib_name);
			}
		}
	}
	
	/**
	 * 得到节点的AttributeValue Boolean
	 * @param element
	 * @param attrib_name 属性名称
	 * @param isReturnNull 是否内容为空 true:是 false:否
	 * @return
	 */
	public static Boolean getAttributeBoolean(Element element,String attrib_name, 
			boolean isReturnNull) throws Exception{
		String value = element.attributeValue(attrib_name);
		if (value == null) {
			if (isReturnNull)
				return null;
			else
				throw new Exception("不能得到节点下｛" + element.getQualifiedName()
					+ "｝的元素：" + attrib_name);
		}
		
		if (value.toLowerCase().equals("true"))
			return Boolean.TRUE;
		else
			return Boolean.FALSE;
	}
	
	/**
	 * 得到节点的AttributeValue Integer
	 * @param element
	 * @param attrib_name 属性名称
	 * @param isReturnNull 是否内容为空 true:是 false:否
	 * @return
	 */
	public static Integer getAttributeInteger(Element element,String attrib_name, 
			boolean isReturnNull) throws Exception{
		String value = element.attributeValue(attrib_name);
		if (value == null) {
			if (isReturnNull)
				return null;
			else
				throw new Exception("不能得到节点下｛" + element.getQualifiedName()
					+ "｝的元素：" + attrib_name);
		}
		if (value.equals(""))
			return null;
		else
			return new Integer(value);
	}
	
	/**
	 * 字符替换
	 *
	 * @param str
	 * @return 
	 */
	public static String swithChar(String str) {
		str = StringUtil.replace(str, "\n", "");
		str = StringUtil.replace(str, "\t", "");
		return str;
	}
	
	/** 
	 * @Description 概要说明: 获取指定节点集合
	 * @param top
	 * @param name
	 * @return List  
	 */
	public static List<Element> getElementsByName(Element top, String name){
        List<Element> elementName = new ArrayList<Element>();
        return getElementsByName(elementName, top, name);
    }

    /** 
     * @Description 概要说明:获取指定节点集合
     * @param elementName
     * @param top
     * @param name
     * @return List  
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
	private static List<Element> getElementsByName(List elementName, Element top, String name){
    	if(top.getName().equals(name))
            elementName.add(top);
        Iterator iter = top.elementIterator();
        if(!iter.hasNext()){
            return elementName;
        }
        Element sub;
        for(; iter.hasNext(); getElementsByName(elementName, sub, name)){
            sub = (Element)iter.next();
        }
        return elementName;
    }
    
    /** 
	 * @Description 概要说明: 获取指定节点子节点集合
	 * @param top
	 * @param name
	 * @return List  
	 */
	public static List<Element> getSonElementsByName(Element top, String name){
        List<Element> elementName = new ArrayList<Element>();
        return getSonElementsByName(elementName, top, name);
    }

    /** 
     * @Description 概要说明:获取指定节点子节点集合
     * @param elementName
     * @param top
     * @param name
     * @return List  
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
	private static List<Element> getSonElementsByName(List elementName, Element top, String name){
        Iterator<Element> iter = top.elementIterator(name);
		for( ; iter.hasNext(); ){
			Element elem = iter.next();
			elementName.add(elem);
		}
        return elementName;
    }
    
    /** 
     * @Description 概要说明: 获取有指定属性的节点集合
     * @param top
     * @param attrName
     * @return List  
     */
	public static List<Element> getElementsByAttrName(Element top, String attrName){
        List<Element> elementName = new ArrayList<Element>();
        return getElementsByAttrName(elementName, top, attrName);
    }

    /** 
     * @Description 概要说明: 获取有指定属性的节点集合
     * @param elementName
     * @param top
     * @param attrName
     * @return List  
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
	private static List<Element> getElementsByAttrName(List elementName, Element top, String attrName){
    	List<Attribute> attrs = top.attributes();
    	for(Attribute attr : attrs){
    		if(attr.getName().equals(attrName))
    			elementName.add(top);
    	}
        Iterator iter = top.elementIterator();
        if(!iter.hasNext()){
            return elementName;
        }
        Element sub;
        for(; iter.hasNext(); getElementsByAttrName(elementName, sub, attrName)){
            sub = (Element)iter.next();
        }
        return elementName;
    }
    
    /** 
     * @Description 概要说明: 获取有指定属性值的节点集合
     * @param top
     * @param attrName
     * @return List  
     */
	public static List<Element> getElementsByAttrValue(Element top, String attrName, String value){
        List<Element> elementName = new ArrayList<Element>();
        return getElementsByAttrValue(elementName, top, attrName, value);
    }

    /** 
     * @Description 概要说明: 获取有指定属性值的节点集合
     * @param elementName
     * @param top
     * @param attrName
     * @return List  
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
	private static List<Element> getElementsByAttrValue(List elementName, Element top, String attrName, String value){
    	List<Attribute> attrs = top.attributes();
    	for(Attribute attr : attrs){
    		if(attr.getName().equals(attrName) 
    				&& attr.getValue().equals(value))
    			elementName.add(top);
    	}
        Iterator iter = top.elementIterator();
        if(!iter.hasNext()){
            return elementName;
        }
        Element sub;
        for(; iter.hasNext(); getElementsByAttrValue(elementName, sub, attrName, value)){
            sub = (Element)iter.next();
        }
        return elementName;
    }
    
    /** 
     * @Description 概要说明: 获取有指定属性值的节点集合
     * @param top
     * @param attrName
     * @return List  
     */
	public static List<Element> getElementsByAttrValueMatch(Element top, String attrName, String value){
        List<Element> elementName = new ArrayList<Element>();
        return getElementsByAttrValueMatch(elementName, top, attrName, value);
    }

    /** 
     * @Description 概要说明: 获取有指定属性值的节点集合
     * @param elementName
     * @param top
     * @param attrName
     * @return List  
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
	private static List<Element> getElementsByAttrValueMatch(List elementName, Element top, String attrName, String value){
    	List<Attribute> attrs = top.attributes();
    	for(Attribute attr : attrs){
    		String name = attr.getName();
    		String attrValue = attr.getValue();
    		if(name.equals(attrName) 
    				&& attrValue.matches(value)){
    			elementName.add(top);
    		}
    	}
        Iterator iter = top.elementIterator();
        if(!iter.hasNext()){
            return elementName;
        }
        Element sub;
        for(; iter.hasNext(); getElementsByAttrValueMatch(elementName, sub, attrName, value)){
            sub = (Element)iter.next();
        }
        return elementName;
    }
    
    /** 
     * @Description 概要说明: 获取叶节点节点集合
     * @param top
     * @return List  
     */
	public static List<Element> getLeafElements(Element top){
        List<Element> elementName = new ArrayList<Element>();
        return getLeafElements(elementName, top);
    }

    /** 
     * @Description 概要说明: 获取叶节点节点集合
     * @param elementName
     * @param top
     * @return List  
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
	private static List<Element> getLeafElements(List elementName, Element top){
        Iterator iter = top.elementIterator();
        if(!iter.hasNext()){
        	elementName.add(top);
            return elementName;
        }
        Element sub;
        for(; iter.hasNext(); getLeafElements(elementName, sub)){
            sub = (Element)iter.next();
        }
        return elementName;
    }
	
    /** 
	 * @Description 概要说明:添加节点属性
	 * @param elm
	 * @param attrName
	 * @param attrValue 
	 * @return  
	 */
	public static void setAttribute(Element elm, String attrName, String attrValue){
		Attribute attr = elm.attribute(attrName);
		if(null != attr){
			elm.remove(attr);
		}
		elm.addAttribute(attrName, attrValue);
	}
	
	/** 
	 * @Description 概要说明: 清空top节点下所有节点
	 * @param top
	 * @return  
	 */
	public static void removeAllElems(Element top){
		for (Iterator<Element> iter = top.elementIterator(); iter.hasNext();) {
			Element element = (Element) iter.next();
			top.remove(element);
		}
	}
    
	/**
	 * 根据节点ID获取节点对象
	 *
	 * @param top
	 * @param _id
	 * @return 
	 */
	public static Element getElementByID(Element top, String _id){
		Element elm = null;
		List<Element> list = getElementsByAttrValue(top, "id", _id);
		if(null != list && 0 != list.size()){
			elm = list.get(0);
		}
		return elm;
	}
	
	/** 
	 * @Description 概要说明:删除所有子孙节点中的a节点
	 * @param srcRoot 
	 * @return  
	 */
	public static void removeAllA(Element srcRoot){
    	// 删除a节点
		List<Element> as = Dom4jUtil.getElementsByName(srcRoot, "a");
		for(Element a : as){
			a.getParent().remove(a);
		}
    }
	
	/** 
	 * @Description 概要说明:获取doc对象
	 * @param inputStream
	 * @return Document  
	 * @throws Exception 
	 */
	public static Document readSVGDocument(InputStream inputStream) throws Exception {
		Document doc = null;
		SAXReader reader = new SAXReader();
		try {
			doc = reader.read(inputStream);
		} catch (Exception e) {
			throw e;
		}
		return doc;
	}
	
	/** 
	 * @Description 概要说明: 获取SVG文件对象
	 * @param url
	 * @return Document  
	 * @throws Exception 
	 */
	public static Document readSVGDocument(String url) throws Exception {
		Document doc = null;
		SAXReader reader = null;
		try {
			reader = new SAXReader();
			doc = reader.read(new File(url));
		} catch (Exception e) {
			throw e;
		}
		
		return doc;
	}
	
	/** 
	 * @Description 概要说明:输出doc对象到磁盘
	 * @param doc
	 * @param url
	 * @return boolean  
	 * @throws IOException 
	 */
	public static boolean writeSVGDocument(Document doc, String url) throws IOException {
		XMLWriter writer = null;
		try {
			OutputFormat format = OutputFormat.createPrettyPrint();
			writer = new XMLWriter(new OutputStreamWriter(
					new FileOutputStream(url), "UTF-8"), format);
			writer.write(doc);
			writer.flush();
		} catch (IOException e) {
			throw e;
		}finally{
			try {
				writer.close();
			} catch (Exception ignore) {
			}
		}
		return true;
	}
}
